package com.aaaa.scheduler.pojo;

import com.aaaa.scheduler.objective.Objective;
import com.aaaa.scheduler.rule.machinerule.CandidateMachineRule;
import com.aaaa.scheduler.rule.machinerule.CandidateMachineSPT;
import com.aaaa.scheduler.rule.processrule.ProcessEDD;
import com.aaaa.scheduler.rule.processrule.ProcessRule;
import com.aaaa.scheduler.rule.processrule.ProcessSPT;
import com.aaaa.scheduler.scheduler.genetic.GeneticConfiguration;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.*;

/**
 * 功能描述：调度案例类，包含了有关调度所有相关信息：工件、工序、工时、设备
 *
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Instance implements Serializable {

    /*
     * 总工时
     */
    private double totalTime;

    /*
     * 总工序数
     */
    private int totalProcessNum;

    /*
     * 总产品数
     */
    private int totalProductNum;

    /*
     * 设备数
     */
    private int machineNum;

    /**
     * 可选设备集合（工序名称  可选设备列表）
     */
    protected Map<String, List<CandidateMachine>> candidateMachineMap = new HashMap<>(); // 可选处理集合（可选设备以及对应的加工时间）

    /**
     * 工序集合（工序名+工序）
     */
    protected Map<String, Process> processMap = new HashMap<>();

    /**
     * 设备集合（设备名+设备）
     */
    protected Map<String, Machine> machineMap = new HashMap<>();

    /**
     * 零件集合（零件名称+零件）
     */
    protected Map<String, Product> productMap = new HashMap<>();

    /**
     * 工单工序在设备选择染色体上对应的index
     */
    protected List<Integer>[] processToIndex;
    /**
     * 每道工序的最大可选设备数
     */
    protected List<Integer> canMachineNumList;

    /**
     * 就绪任务集合
     */
    protected TreeSet<Process> readyTaskS = new TreeSet<Process>(new ProcessSPT());//默认规则

    /**
     * 工序任务比较器
     */
    protected ProcessRule processComparator = new ProcessEDD();
    /**
     * 机器选择比较器
     */
    protected CandidateMachineRule candidateMachineRule = new CandidateMachineSPT();


    /*
     * 算法名字
     */
    protected String altorighmName;
    /*
     * 初始化染色体的方式
     */
    private String ChromosomeCreateName;

    /**
     * 是否保存动态分派
     */
    protected boolean wirteDynamic = false;

    /**
     * 已分派的总工时（计算奖励时使用）
     */
    protected double totalAssignedTaskWork;

    /**
     * 调度目标
     */
//    protected Objective objective;
    protected List<Objective> objectiveList = new ArrayList<>();//多目标


    /**
     * 上一步的调度目标值
     */
    protected double[] lastObjectiveValue;


    /**
     * 案例调度可选的动作或规则集合
     */
    protected List<ProcessRule> operationRules = new ArrayList<>();




    /**
     * 功能描述：对工件和工序进行初始化
     *
     */
    public void init() {
        // 默认目标为制造期
//        this.objective = new ObjectiveCmax();
        this.objectiveList = GeneticConfiguration.buildObjectives();
        this.lastObjectiveValue = new double[this.objectiveList.size()];
        processMap.clear();
        for (Product product : productMap.values()) {
//            double remainWork = 0d;
            int iSize = product.getOpList().size();
            totalProcessNum += iSize;
            for (int j = iSize - 1; j >= 0; j--) {
                Process process = product.getOpList().get(j);
//                remainWork += process.getWorkTime();
//                process.setRemainWorkTime(remainWork);
                // 刷新剩余工序数
                process.setRemainProcessNum(iSize - j);
                process.setProduct(product);
                // System.out.println("工序：" + process.get(process.getName()).getName());
                //设置前后工序
                if (iSize > 1) {
                    if (j == iSize - 1) {
                        process.setPrepOp(product.getOpList().get(j - 1));
                    } else if (j == 0) {
                        process.setSuccOp(product.getOpList().get(j + 1));
                    } else {
                        process.setPrepOp(product.getOpList().get(j - 1));
                        process.setSuccOp(product.getOpList().get(j + 1));
                    }
                }
                processMap.put(process.getName(), process);
            }
//            product.setTotalWorkTime(remainWork);
        }
        class AssginedOpComp implements Comparator<Process>, Serializable{
            @Override
            public int compare(Process o1, Process o2) {
                // TODO Auto-generated method stub
                if (o1.getStart() > o2.getStart()) {
                    return 1;
                } else if (o1.getStart() < o2.getStart()) {
                    return -1;
                } else {
                    return 0;
                }
            }
        }
        // 设置机床上已安排任务的比较器
        for (Machine machine : machineMap.values()) {
            TreeSet<Process> queueList = new TreeSet<>(new AssginedOpComp());
            machine.setQueueList(queueList);
        }
    }

    public void reset() {
//        this.lastObjectiveValue = 0;
//        this.objective.setObjectiveValue(0);
        Arrays.fill(this.lastObjectiveValue, 0);
        for (Objective objective : this.objectiveList) {
            objective.setObjectiveValue(0);
        }
        this.totalAssignedTaskWork = 0;

        for (Process process : processMap.values()) {
            // 清除计划时间
            process.setStart(0);
            process.setFinish(0);
            // 清除已安排设备
            process.setMachineID(-1);
            process.setMachineName("");
            // 初始为未调度状态
            process.setState(Process.Unassigned_state);
            process.setFixedMachineID(-1);
        }
        for (Machine machine : machineMap.values()) {
            // 清除设备已安排任务
            machine.getQueueList().clear();
            // 清除工时
            machine.setAssignedTaskWork(0);
            // 清除负荷率和利用率
            machine.setLoadRation(0);
            machine.setUtilRation(0);
        }
        for (Product product : productMap.values()) {
            product.setStart(0);
            product.setFinish(0);
        }
    }
}
